//
//  Move.h
//  phi_four
//
//  Created by Snir Gazit on 3/9/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#ifndef Move_h
#define Move_h

#include "../HelpLibs/RandomGen.h"
#include "Lattice.h"
#include "../HelpLibs/QmcParameters.h"
namespace ba = boost::accumulators;

typedef RandomVariable<MTGen, UniReal> UniRealVariable;
typedef RandomVariable<MTGen, UniInt> UniIntVariable;
typedef RandomVariable<MTGen, Binomial> BinomialVariable;
typedef RandomVariable<MTGen, Discrete> DiscreteVariable;
typedef UniRealVariable::param_type UniRealVariableParams;
typedef UniIntVariable::param_type UniIntVariableParams;
typedef BinomialVariable::param_type BinomialVariableParams;
typedef DiscreteVariable::param_type DiscreteVariableParams;

using namespace std;

class Move {
protected:
	MTGen *eng_;
	Lattice *lat_;
	UniRealVariable zeroOne_;
public:
	void init(MTGen * eng, Lattice *lat);
	bool makeMove();
	bool accept(double p);
	bool checkMove();
};

// Worm Alg Moves
class ShiftMove: public Move {
	typedef boost::array<BondType*, 2 * DIM> BondArray;
	UniIntVariable chooseMove_;
	BoltzWeightType CreateRatio_, RemoveRatio_;
public:
	void init(MTGen *eng, Lattice *lat, QmcParameters &qmcParameters,
			BoltzWeightType boltzRatio);
	bool makeMove();
	int& getBondVal(BondArray &bondArray, int dir, CreateRemove createRemove);
	void setCoupeling(BoltzWeightType boltzRatio);
};

class CreatePairMove: public Move {
	typedef boost::array<BondType*, 2 * DIM> BondArray;
	UniIntVariable chooseSite_;
	UniIntVariable chooseMove_;
	BoltzWeightType boltzRatio_;
public:
	void init(MTGen *eng, Lattice *lat, QmcParameters &qmcParameters,
			BoltzWeightType boltzRatio);
	void setCoupeling(BoltzWeightType boltzRatio);
	bool makeMove(int sec);
	int& getBondVal(BondArray &bondArray, int dir, CreateRemove createRemove);
};

double addRatio(int m,int n);
double removeRatio(int m,int n);


#endif
